package com.bear.atlassianmcp.oauth.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * OAuth 1.0a 签名工具类
 * 实现 RSA-SHA1 签名算法
 */
@Component
public class OAuthSignatureUtil {
    
    private static final Logger logger = LoggerFactory.getLogger(OAuthSignatureUtil.class);
    
    /**
     * 生成 OAuth 1.0a 签名
     * 
     * @param httpMethod HTTP 方法 (GET, POST, etc.)
     * @param baseUrl 基础 URL
     * @param oauthParams OAuth 参数
     * @param tokenSecret Token Secret (对于 Request Token 请求为空字符串)
     * @param privateKeyContent 私钥内容或文件路径
     * @return 生成的签名
     */
    public String generateSignature(String httpMethod, String baseUrl, Map<String, String> oauthParams, 
                                  String tokenSecret, String privateKeyContent) {
        try {
            // 1. 构建签名基础字符串
            String signatureBaseString = buildSignatureBaseString(httpMethod, baseUrl, oauthParams);
            logger.debug("Signature base string: {}", signatureBaseString);
            
            // 2. 构建签名密钥
            String signingKey = buildSigningKey("", tokenSecret); // Consumer Secret 通常为空
            logger.debug("Signing key: {}", signingKey);
            
            // 3. 使用 RSA-SHA1 算法生成签名
            String signature = signWithRSASHA1(signatureBaseString, privateKeyContent);
            logger.debug("Generated signature: {}", signature);
            
            return signature;
            
        } catch (Exception e) {
            logger.error("Failed to generate OAuth signature: {}", e.getMessage(), e);
            throw new RuntimeException("Failed to generate OAuth signature", e);
        }
    }
    
    /**
     * 构建签名基础字符串
     */
    private String buildSignatureBaseString(String httpMethod, String baseUrl, Map<String, String> params) {
        // 1. 规范化 HTTP 方法
        String normalizedMethod = httpMethod.toUpperCase();
        
        // 2. 规范化 URL (移除查询参数和片段)
        String normalizedUrl = normalizeUrl(baseUrl);
        
        // 3. 规范化参数
        String normalizedParams = normalizeParameters(params);
        
        // 4. 构建签名基础字符串
        return normalizedMethod + "&" + 
               urlEncode(normalizedUrl) + "&" + 
               urlEncode(normalizedParams);
    }
    
    /**
     * 规范化 URL
     */
    private String normalizeUrl(String url) {
        // 移除查询参数和片段
        int queryIndex = url.indexOf('?');
        if (queryIndex != -1) {
            url = url.substring(0, queryIndex);
        }
        
        int fragmentIndex = url.indexOf('#');
        if (fragmentIndex != -1) {
            url = url.substring(0, fragmentIndex);
        }
        
        return url;
    }
    
    /**
     * 规范化参数
     */
    private String normalizeParameters(Map<String, String> params) {
        // 使用 TreeMap 自动排序
        TreeMap<String, String> sortedParams = new TreeMap<>();
        
        // 对参数进行 URL 编码并排序
        for (Map.Entry<String, String> entry : params.entrySet()) {
            String key = urlEncode(entry.getKey());
            String value = urlEncode(entry.getValue());
            sortedParams.put(key, value);
        }
        
        // 构建参数字符串
        return sortedParams.entrySet().stream()
                .map(entry -> entry.getKey() + "=" + entry.getValue())
                .collect(Collectors.joining("&"));
    }
    
    /**
     * 构建签名密钥
     */
    private String buildSigningKey(String consumerSecret, String tokenSecret) {
        return urlEncode(consumerSecret) + "&" + urlEncode(tokenSecret != null ? tokenSecret : "");
    }
    
    /**
     * 使用 RSA-SHA1 算法签名
     */
    private String signWithRSASHA1(String data, String privateKeyContent) throws Exception {
        // 加载私钥
        PrivateKey privateKey = loadPrivateKey(privateKeyContent);
        
        // 创建签名对象
        Signature signature = Signature.getInstance("SHA1withRSA");
        signature.initSign(privateKey);
        signature.update(data.getBytes(StandardCharsets.UTF_8));
        
        // 生成签名
        byte[] signatureBytes = signature.sign();
        
        // Base64 编码
        return Base64.getEncoder().encodeToString(signatureBytes);
    }
    
    /**
     * 加载私钥
     */
    private PrivateKey loadPrivateKey(String privateKeyContent) throws Exception {
        String keyContent;
        
        // 判断是文件路径还是直接的密钥内容
        //if (privateKeyContent.startsWith("-----BEGIN")) {
            // 直接的密钥内容
            keyContent = privateKeyContent;
        /*} else {
            // 文件路径
            try {
                keyContent = Files.readString(Paths.get(privateKeyContent), StandardCharsets.UTF_8);
            } catch (IOException e) {
                logger.error("Failed to read private key file: {}", privateKeyContent);
                throw new RuntimeException("Failed to read private key file", e);
            }
        }*/
        
        // 清理密钥内容
        keyContent = keyContent
                .replace("-----BEGIN PRIVATE KEY-----", "")
                .replace("-----END PRIVATE KEY-----", "")
                .replace("-----BEGIN RSA PRIVATE KEY-----", "")
                .replace("-----END RSA PRIVATE KEY-----", "")
                .replaceAll("\\s", "");
        
        // 解码 Base64
        byte[] keyBytes = Base64.getDecoder().decode(keyContent);
        
        // 创建私钥对象
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        
        return keyFactory.generatePrivate(keySpec);
    }
    
    /**
     * URL 编码
     */
    private String urlEncode(String value) {
        if (value == null) {
            return "";
        }
        
        try {
            return URLEncoder.encode(value, StandardCharsets.UTF_8.name())
                    .replace("+", "%20")
                    .replace("*", "%2A")
                    .replace("%7E", "~");
        } catch (Exception e) {
            throw new RuntimeException("Failed to URL encode: " + value, e);
        }
    }
    
    /**
     * 构建 Authorization 头部
     */
    public String buildAuthorizationHeader(Map<String, String> oauthParams) {
        StringBuilder header = new StringBuilder("OAuth ");
        
        boolean first = true;
        for (Map.Entry<String, String> entry : oauthParams.entrySet()) {
            if (!first) {
                header.append(", ");
            }
            
            header.append(urlEncode(entry.getKey()))
                  .append("=\"")
                  .append(urlEncode(entry.getValue()))
                  .append("\"");
            
            first = false;
        }
        
        return header.toString();
    }
    
    /**
     * 为 API 请求生成 OAuth 授权头
     * 
     * @param httpMethod HTTP 方法
     * @param url 请求 URL
     * @param consumerKey Consumer Key
     * @param accessToken Access Token
     * @param accessTokenSecret Access Token Secret
     * @param privateKeyContent 私钥内容
     * @return Authorization 头部值
     */
    public String generateAuthorizationHeader(String httpMethod, String url, String consumerKey,
                                            String accessToken, String accessTokenSecret, 
                                            String privateKeyContent) {
        try {
            // 构建 OAuth 参数
            Map<String, String> oauthParams = new TreeMap<>();
            oauthParams.put("oauth_consumer_key", consumerKey);
            oauthParams.put("oauth_token", accessToken);
            oauthParams.put("oauth_signature_method", "RSA-SHA1");
            oauthParams.put("oauth_timestamp", String.valueOf(System.currentTimeMillis() / 1000));
            oauthParams.put("oauth_nonce", generateNonce());
            oauthParams.put("oauth_version", "1.0");
            
            // 生成签名
            String signature = generateSignature(httpMethod, url, oauthParams, 
                                               accessTokenSecret, privateKeyContent);
            oauthParams.put("oauth_signature", signature);
            
            // 构建 Authorization 头
            return buildAuthorizationHeader(oauthParams);
            
        } catch (Exception e) {
            logger.error("Failed to generate authorization header: {}", e.getMessage(), e);
            throw new RuntimeException("Failed to generate authorization header", e);
        }
    }
    
    /**
     * 生成随机 nonce
     */
    private String generateNonce() {
        return String.valueOf(System.currentTimeMillis()) + String.valueOf(Math.random()).substring(2);
    }
    
    /**
     * 验证私钥格式
     */
    public boolean validatePrivateKey(String privateKeyContent) {
        try {
            loadPrivateKey(privateKeyContent);
            return true;
        } catch (Exception e) {
            logger.error("Invalid private key: {}", e.getMessage());
            return false;
        }
    }
    
    /**
     * 生成测试用的 RSA 密钥对 (仅用于开发测试)
     */
    public KeyPair generateTestKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(2048);
        return keyGen.generateKeyPair();
    }
    
    /**
     * 将私钥转换为 PEM 格式字符串 (仅用于开发测试)
     */
    public String privateKeyToPem(PrivateKey privateKey) {
        byte[] encoded = privateKey.getEncoded();
        String base64 = Base64.getEncoder().encodeToString(encoded);
        
        StringBuilder pem = new StringBuilder();
        pem.append("-----BEGIN PRIVATE KEY-----\n");
        
        // 每 64 个字符换行
        for (int i = 0; i < base64.length(); i += 64) {
            int end = Math.min(i + 64, base64.length());
            pem.append(base64, i, end).append("\n");
        }
        
        pem.append("-----END PRIVATE KEY-----");
        return pem.toString();
    }
}
